/////////////////////////////////////////////////////////////////////////////
// CFlexThread class implements a simple thread wrapper.
//
// Version 1.0 - 15 june 2007
//
// Copyright (c) 2007 by FlexByte Software (http://flexbyte.com)
// All rights reserved.
//
// You may use the source code in any product (freeware, commercial, etc.). 
// You may modify the source code as you want except 
// you cannot modify the copyright details at the top of each module.
// If you have a web site or blog give a link to our web site, flexbyte.com
/////////////////////////////////////////////////////////////////////////////
#include "FlexThread.h"
#include "FlexException.h"
/////////////////////////////////////////////////////////////////////////////
CFlexThread::CFlexThread()
: m_hThread( NULL )
, m_pExec( NULL )
{
}
/////////////////////////////////////////////////////////////////////////////
CFlexThread::~CFlexThread(void)
{
	if( m_hThread )
		Exit();
}
/////////////////////////////////////////////////////////////////////////////
void CFlexThread::Execute(IExecutable * pExec)
{
	assert( pExec );
	assert( !m_hThread );

	m_pExec = pExec;
	m_hThread = ::CreateThread( 
		NULL, 
		0, 
		reinterpret_cast< LPTHREAD_START_ROUTINE >( CFlexThread::_Thread ),
		pExec,
		0,
		&m_dwThreadId
		);
	if( !m_hThread )
		throw CFlexException( ::GetLastError() );
}
/////////////////////////////////////////////////////////////////////////////
void CFlexThread::Exit()
{
	if( m_hThread )
	{
		assert( m_pExec );
		m_pExec->Break();
		::CloseHandle( m_hThread );
		m_hThread = NULL;
	}
}
/////////////////////////////////////////////////////////////////////////////
void CFlexThread::Wait(DWORD dwTimeout/* = INFINITE*/)
{
	::WaitForSingleObject( m_hThread, dwTimeout );
}
void CFlexThread::MsgWait(DWORD dwTimeout/* = INFINITE*/)
{
	while   (TRUE)
	{
		  DWORD   result   ;
		  MSG   msg   ;

		  //   Read   all   of   the   messages   in   this   next   loop,
		  //   removing   each   message   as   we   read   it.
		  while   (PeekMessage(&msg,   NULL,   0,   0,   PM_REMOVE))
		  {
				  //   If   it's   a   quit   message,   we're   out   of   here.
				  if   (msg.message   ==   WM_QUIT)
						  return;
				  //   Otherwise,   dispatch   the   message.
				  DispatchMessage(&msg);
		  }   //   End   of   PeekMessage   while   loop.

		  //   Wait   for   any   message   sent   or   posted   to   this   queue
		  //   or   for   one   of   the   passed   handles   be   set   to   signaled.
		  result   =   MsgWaitForMultipleObjects(1,   &m_hThread,
							FALSE,   INFINITE,   QS_ALLINPUT);

		  if   (result   !=   WAIT_OBJECT_0)
				  continue;
		  else
			return;
	}
}
/////////////////////////////////////////////////////////////////////////////
DWORD CFlexThread::_Thread(LPVOID param)
{
	IExecutable * pExec = static_cast< IExecutable * >( param );
	assert( pExec );
	pExec->Execute();
	return 0;
}
/////////////////////////////////////////////////////////////////////////////
